import * as d3 from 'd3'
export class PieChart {
  data = ''
  divId = ''
  xLabel = ''
  yLabel = ''
  title = ''
  innerRadius = '0%'
  outerRadius = '100%'
  basicRadius = 0
  itemsName = []
  chart = {}
  color = d3.scaleOrdinal(d3.schemeCategory10)

  constructor (divId) {
    this.divId = divId
  }

  draw () {
    this.initChart()
    this.initLayout()
    this.drawLabel()
    this.drawLegend()
    this.drawchart()
  }
  update () {
    this.initLayout()
    this.drawLegend()
    this.drawchart()
  }
  initChart () {
    this.chart.padding = {
      left: 20,
      right: 50,
      top: 20,
      bottom: 20
    }
    this.chart.divHeight = document.getElementById(this.divId).offsetHeight -
      this.chart.padding.top -
      this.chart.padding.bottom
    this.chart.divWidth = document.getElementById(this.divId).offsetWidth -
      this.chart.padding.left -
      this.chart.padding.right

    this.basicRadius = Math.min(this.chart.divHeight, this.chart.divWidth) / 2

    this.chart.svg = d3.select('#' + this.divId)
      .append('svg')
      .attr('width', this.chart.divWidth +
        this.chart.padding.left +
        this.chart.padding.right
      )
      .attr('height', this.chart.divHeight +
        this.chart.padding.top +
        this.chart.padding.bottom
      )
      .attr('class', 'svg_chart')
  }

  initLayout () {
    this.chart.pie = d3.pie()
      .sort(null)
      .value(d => d.value)
      .padAngle(0.01)

    this.chart.arc = d3.arc()
      .innerRadius(this.basicRadius * parseFloat(this.innerRadius.split('%')).toFixed(1) / 100)
      .outerRadius(this.basicRadius * parseFloat(this.outerRadius.split('%')).toFixed(1) / 100)
  }

  drawchart () {
    let arc = this.chart.arc
    let arcs = this.chart.svg.selectAll('.arc')
      .data(this.chart.pie(this.data), d => d.data.name)

    let exitT = d3.transition()
      .duration(1000)

    let t = d3.transition(exitT)

    let enterT = d3.transition(t)

    arcs.select('path')
      .transition(t)
      .attrTween('d', arcTween)

    arcs.select('text')
      .transition(t)
      .attr('transform', d => 'translate(' + this.chart.arc.centroid(d) + ')')

    let arcEnter = arcs.enter()
      .append('g')
      .attr('class', 'arc')
      .attr('transform', 'translate(' + this.chart.divWidth / 2 + ',' + this.chart.divHeight / 2 + ')')

    arcEnter.append('path')
      .attr('d', d => this.chart.arc({
        startAngle: d.startAngle,
        endAngle: d.startAngle
      }))
      .style('fill', (d, i) => this.color(i))
      .each(function (d) {
        this._current = {
          startAngle: d.startAngle,
          endAngle: d.startAngle
        }
      })

    arcEnter.append('text')
      .text(d => d.value)
      .attr('transform', d => 'translate(' + this.chart.arc.centroid(d) + ')')
      .attr('font-size', 1e-6)

    arcEnter.select('path')
      .transition(enterT)
      .attrTween('d', arcTween)

    arcEnter.select('text')
      .transition(enterT)
      .attr('transform', d => 'translate(' + this.chart.arc.centroid(d) + ')')
      .attr('font-size', 14)
      .text(d => d.value)

    let arcExit = arcs.exit()
      .transition(exitT)
      .remove()

    arcExit.select('path')
      .attrTween('d', exitTween)

    arcExit.select('text')
      .attr('font-size', 1e-6)

    function arcTween (a) {
      var i = d3.interpolate(this._current, a)
      this._current = i(0)
      return function (t) {
        return arc(i(t))
      }
    }

    function exitTween (d) {
      var end = Object.assign({}, this._current, { startAngle: this._current.endAngle })
      var i = d3.interpolate(d, end)
      return function (t) {
        return arc(i(t))
      }
    }
  }
  drawLegend () {
    let legendWidth = 15
    let legendHeight = 15
    let legends = this.chart.svg
      .selectAll('.legend')
      .data(this.itemsName, d => d)

    let legendEnter = legends.enter()
      .append('g')
      .attr('class', 'legend')

    legendEnter.append('rect')
      .attr('x', this.chart.divWidth + 5)
      .attr('y', (d, i) => this.chart.padding.top + legendHeight * i)
      .attr('width', 0)
      .attr('height', legendHeight - 5)
      .style('fill', (d, i) => this.color(i))

    legendEnter.append('text')
      .attr('x', this.chart.divWidth + legendWidth * 1.3 + 5)
      .attr('y', (d, i) => this.chart.padding.top + legendHeight * i + legendHeight / 2)
      .text(String)
      .style('font-size', 1e-6)

    let legendUpdate = legendEnter.merge(legends)

    legendUpdate.select('rect')
      .transition()
      .duration(750)
      .attr('width', legendWidth)

    legendUpdate.select('text')
      .transition()
      .duration(750)
      .style('font-size', 10)

    let legendExit = legends.exit()
      .transition()
      .duration(750)
      .remove()

    legendExit.select('rect')
      .attr('width', 0)

    legendExit.select('text')
      .style('stroke-opacity', 1e-6)
  }
  drawLabel () {
    this.chart.svg
      .append('text')
      .attr('x', this.chart.divWidth * 0.45)
      .attr('y', this.chart.divHeight + this.chart.padding.bottom * 1.7)
      .text(this.title)
  }
  sort () {
    this.chart.pie.sort((a, b) => (a - b))
    this.drawchart()
  }
}
